package com.wallace.downloadserver.redis

import com.fasterxml.jackson.annotation.JsonAutoDetect
import com.fasterxml.jackson.annotation.JsonTypeInfo
import com.fasterxml.jackson.annotation.PropertyAccessor
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator
import org.springframework.data.redis.connection.RedisStandaloneConfiguration
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory
import org.springframework.data.redis.core.RedisTemplate
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer
import org.springframework.data.redis.serializer.StringRedisSerializer
import org.springframework.stereotype.Component
import javax.annotation.PostConstruct
import javax.annotation.Resource

/**
 * @Description:
 * 负责连接和切换redis数据库
 * @author Wallace
 * @Date 2022/1/20 17:32
 */
@Component
class RedisManager {

    @Resource
    private val config: RedisConfig? = null

    //RedisTemplate实例
    private val redisTemplateMap: HashMap<Int, RedisTemplate<String, Any>> = HashMap()

    fun getTokenDB(): RedisTemplate<String, Any> {
        return redisTemplateMap[config!!.redisTokenDB]!!
    }

    fun getAesKeyDB(): RedisTemplate<String, Any> {
        return redisTemplateMap[config!!.redisAesKeyDB]!!
    }

    fun getNettyAesKeyDB(): RedisTemplate<String, Any> {
        return redisTemplateMap[config!!.redisNettyAesKeyDB]!!
    }

    fun getFileDB(): RedisTemplate<String, Any> {
        return redisTemplateMap[config!!.redisFileDB]!!
    }

    /**
     * 初始化连接池
     */
    @PostConstruct
    fun initRedisTemplate() {
        redisTemplateMap[config!!.redisTokenDB] = initRedisTemplate(config.redisTokenDB)
        redisTemplateMap[config.redisAesKeyDB] = initRedisTemplate(config.redisAesKeyDB)
        redisTemplateMap[config.redisNettyAesKeyDB] = initRedisTemplate(config.redisNettyAesKeyDB)
        redisTemplateMap[config.redisFileDB] = initRedisTemplate(config.redisFileDB)
    }

    private fun redisConnection(db: Int): LettuceConnectionFactory {
        val server = RedisStandaloneConfiguration()
        server.hostName = config!!.host!!
        server.database = db
        server.port = config.port
        val factory = LettuceConnectionFactory(server)
        factory.afterPropertiesSet()
        return factory
    }

    private fun initRedisTemplate(db: Int): RedisTemplate<String, Any> {
        val om = ObjectMapper()
        om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance,
                ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.PUBLIC_ONLY)
        val jackson2JsonRedisSerializer = Jackson2JsonRedisSerializer(Any::class.java)
        jackson2JsonRedisSerializer.setObjectMapper(om)
        val stringRedisSerializer = StringRedisSerializer()
        val template = RedisTemplate<String, Any>()
        template.setConnectionFactory(redisConnection(db))
        template.keySerializer = stringRedisSerializer
        template.hashKeySerializer = stringRedisSerializer
        template.valueSerializer = jackson2JsonRedisSerializer
        template.hashValueSerializer = jackson2JsonRedisSerializer
        template.afterPropertiesSet()
        return template
    }
}